<?php

class Nina_String
{
	protected $string;

	/**
	 * Constructor
	 * @param string [$string=''] The string to manipulate
	 */
	public function __construct($string = '') {
		$this->string = $string;
	}

	/**
	 * Return the string
	 * @return string
	 */
	public function get() {
		return $this->string;
	}

	/**
	 * Trim whitespace from the string
	 * @return string
	 */
	public function trim() {
		return trim($this->string);
	}
	
	/**
	 * Get the length of the string
	 * @return integer
	 */
	public function length() {
		return strlen($this->string);
	}
	
	/**
	 * Convert to upper case
	 * @return string
	 */
	public function upcase() {
		return strtoupper($this->string);
	}
	
	/**
	 * Convert to lower case
	 * @return string
	 */
	public function downcase() {
		return strtolower($this->string);
	}
	
	/**
	 * Capitalise
	 * @return string
	 */
	public function capitalise() {
		return ucfirst($this->string);
	}
	
	/**
	 * Produce MD5 encoding of the string
	 * @return string
	 */
	public function md5() {
		return md5($this->string);
	}
	
	/**
	 * Count the number of words in the string
	 * @return integer
	 */
	public function wordcount() {
		return str_word_count($this->string);
	}
	
	/**
	 * Bind other values into the string
	 * @return string
	 */
	public function sprintf($arg1 = null, $arg2 = null, $arg3 = null) {
		return sprintf($this->string, $arg1, $arg2, $arg3);
	}

	/**
	 * Check if the string contains a search string
	 * @param string $search The search string
	 * @param boolean [$case_sensitive=false] Case sensitive search
	 * @return boolean
	 */
	public function contains($search, $case_sensitive = false) {
		if ($case_sensitive)
			return (strpos($this->string, $search) !== false);
		else
			return (stripos($this->string, $search) !== false);
	}

	/**
	 * Get the position of a search string
	 * @param string $search The search string
	 * @param boolean [$case_sensitive=false] Case sensitive search
	 * @return integer|false
	 */
	public function position($search, $case_sensitive = false) {
		if ($case_sensitive)
			return strpos($this->string, $search);
		else
			return stripos($this->string, $search);
	}

	/**
	 * Produce a substring
	 * @param integer $start The start index
	 * @param integer [$length=null] The length of the produced substring
	 * @return string
	 */
	public function substring($start, $length = null) {
		return substr($this->string, $start, $length);
	}

	/**
	 * Replace a substring
	 * @param string $search The text to search for
	 * @param string $substitution The text to substitute
	 * @return string
	 */
	public function replace($search, $substitution) {
		return str_replace($search, $substitution, $this->string);
	}
	
	/**
	 * Shorten the string to a max character length
	 * @param integer $characters The number of characters to shorten to
	 * @param boolean [$ellipsis=true] Show ellipsis
	 * @return string
	 */
	public function shorten($characters, $ellipsis = true) {
		if($this->length() <= $characters)
			return $this->string;
		else {
			$str = $this->substring(0, $characters);
			
			if($ellipsis)
				$str .= '...';
			
			return $str;
		}
	}
	
	/**
	 * Shorten the string to a max word length
	 * @param integer $words The number of words to shorten to
	 * @param boolean [$ellipsis=true] Show ellipsis
	 * @return string
	 */
	public function shortenWords($words, $ellipsis = true) {
		$exploded = explode(' ', $this->string);
		if(count($exploded) <= $words)
			return $this->string;
		else {
			$str = implode(' ', array_slice($exploded, 0, $words));
			
			if($ellipsis)
				$str .= '...';
			
			return $str;
		}
	}
	
	/**
	 * Sanitise the string
	 * @return string
	 */
	public function sanitise() {
		return trim(htmlentities(stripslashes($this->string)));
	}
	
	/**
	 * Camelise the string
	 * @return string
	 */
	public function camelise() {
		return str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower($this->string))));
	}

	/**
	 * Sanitise the string
	 * @return string
	 */
	public function sanitize() {
		return $this->sanitise();
	}

	/**
	 * Camelise the string
	 * @return string
	 */
	public function camelize() {
		return $this->camelise();
	}
	
	/**
	 * Underscore the string
	 * @return string
	 */
	public function underscore() {
		return strtolower(preg_replace("/(?<=[a-z0-9])([A-Z])/", "_\$1", $this->string));
	}
	
	/**
	 * Highlight a word in the string
	 * @param string $word The word
	 * @return string
	 */
	public function highlight($word) {
		return str_ireplace($word, '<span class="highlight">' . $word . '</span>', $this->string);
	}

	/**
	 * Extract the portions of a string before and after the given word/phrase 
	 * @param string $phrase The phrase
	 * @param boolean [$concatenate=true] Concatenate matches
	 * @param boolean [$highlight=false] Highlight the word/phrase
	 * @param integer [$padding=5] The number of words to show either side
	 * @return array
	 */
	public function extractPhrase($phrase, $concatenate = true, $highlight = false, $padding = 5) {
		if(preg_match_all('/(?:\s?\S+\s?){0,' . $padding . '}' . $phrase . '(?:\s?\S+\s?){0,' . $padding . '}/i', $this->string, $matches)) {
			$phrase_highlights = array();

			foreach($matches[0] as $i => $match) {
				$prefix = (!($i == 0 && strtolower(substr($this->string, 0, strlen($match))) == strtolower($match)));
				$postfix = (!($i == (count($matches[0])-1) && strtolower(substr($this->string, strlen($this->string) - strlen($match))) == strtolower($match)));
				
				if ($highlight)
					$match = self::doHighlight($match, $phrase);
				
				$phrase_highlights[] = ($prefix ? '...' : '') .$match . ($postfix ? '...' : '');
			}

			return ($concatenate) ? implode("\n", $phrase_highlights) : $phrase_highlights;
		}
		else
			return ($concatenate) ? $this->string : array($this->string);
	}
	
	/**
	 * Shorten the string to a max character length
	 * @param string $str The string to shorten
	 * @param integer $words The number of words to shorten to
	 * @param boolean [$ellipsis=true] Show ellipsis
	 * @return string
	 */
	public static function doShorten($str, $characters, $ellipsis = true) {
		$my_str = new Nina_String($str);
		return $my_str->shorten($characters, $ellipsis);
	}
	
	/**
	 * Shorten the string to a max word length
	 * @param string $str The string to shorten
	 * @param integer $words The number of words to shorten to
	 * @param boolean [$ellipsis=true] Show ellipsis
	 * @return string
	 */
	public static function doShortenWords($str, $words, $ellipsis = true) {
		$my_str = new Nina_String($str);
		return $my_str->shortenWords($words, $ellipsis);
	}
	
	/**
	 * Sanitise the string
	 * @param string $str The string to sanitise
	 * @return string
	 */
	public static function doSanitise($str) {
		$my_str = new Nina_String($str);
		return $my_str->sanitise();
	}
	
	/**
	 * Camelise the string
	 * @param string $str The string to camelise
	 * @return string
	 */
	public static function doCamelise($str) {
		$my_str = new Nina_String($str);
		return $my_str->camelise();
	}
	
	/**
	 * Sanitise the string
	 * @param string $str The string to sanitise
	 * @return string
	 */
	public static function doSanitize($str) {
		return self::doSanitise($str);
	}
	
	/**
	 * Camelise the string
	 * @param string $str The string to camelise
	 * @return string
	 */
	public static function doCamelize($str) {
		return self::doCamelise($str);
	}
	
	/**
	 * Underscore the string
	 * @param string $str The string to underscore
	 * @return string
	 */
	public static function doUnderscore($str) {
		$my_str = new Nina_String($str);
		return $my_str->underscore();
	}
	
	/**
	 * Highlight a word in the string
	 * @param string $str The string to highlight
	 * @param string $word The word
	 * @return string
	 */
	public static function doHighlight($str, $word) {
		$my_str = new Nina_String($str);
		return $my_str->highlight($word);
	}

	/**
	 * Extract the portions of a string before and after the given word/phrase
	 * @param string $str The string to extract from 
	 * @param string $phrase The phrase
	 * @param boolean [$concatenate=true] Concatenate matches
	 * @param boolean [$highlight=false] Highlight the word/phrase
	 * @param integer [$padding=5] The number of words to show either side
	 * @return array
	 */
	public function doExtractPhrase($str, $phrase, $concatenate = true, $highlight = false, $padding = 5) {
		$my_str = new Nina_String($str);
		return $my_str->extractPhrase($phrase, $concatenate, $highlight, $padding);
	}
	
	/**
	 * Create a random password string
	 * @param integer [$no_of_chars=8] Number of characters
	 * @return string
	 */
	public static function createRandomPassword($no_of_chars = 8) {
		$chars = "abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		srand((double)microtime()*1000000);
		
		$pass = '';
		for ($i = 0; $i < $no_of_chars; $i++) {
			$num = rand(0, strlen($chars) - 1);
			$pass .= substr($chars, $num, 1);
		}
		
		return $pass;
	}
}	